﻿using AutoMapper;
using Mes.Infrastructure.Data.BoundedContext.Extensions;
using Mes.Domain.BoundedContext;
using System.Linq.Expressions;
using Mes.Application.Common;
using Mes.Application.Common.Resource;
using Mes.Application.DTO.Inputs.MasterData;
using Mes.Application.DTO.Results.MasterData;
using Mes.Domain.BoundedContext.Entities.MasterData;
using Mes.Infrastructure.Data.BoundedContext.Repositories.MasterData;

namespace Mes.Application.Services.MasterData
{
    public class MaterialClassService : IMaterialClassService
    {
        private readonly IMaterialClassRepository _materialClassRepository;
        private readonly IMapper _mapper;
        private readonly IMaterialClassTypeRepository _materialClassTypeRepository;
        public MaterialClassService(IMapper mapper, IMaterialClassRepository materialClassRepository, IMaterialClassTypeRepository materialClassTypeRepository)
        {
            if (mapper == null || materialClassRepository == null || materialClassTypeRepository == null)
            {
                throw new ArgumentNullException();
            }
            _mapper = mapper;
            _materialClassRepository = materialClassRepository;
            _materialClassTypeRepository = materialClassTypeRepository;
        }

        /// <summary>
        /// 新增物料类
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task AddMaterialClassAsync(AddMaterialClassInput input)
        {
            if (!await _materialClassTypeRepository.ExistsAsync(x => x.Id == input.TypeId && x.Type == input.TypeName))
            {
                throw new CustomException(Messages.MaterialClassTypeNotFound);
            }
            if (await _materialClassRepository.ExistsAsync(x => x.Code == input.Code || x.Name == input.Name))
            {
                throw new CustomException(Messages.MaterialClassDuplication);
            }
            var materialClass = _mapper.Map<MaterialClass>(input);
            await _materialClassRepository.AddAsync(materialClass);
            int status = await _materialClassRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 编辑物料类
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task UpdateMaterialClassAsync(UpdateMaterialClassInput input)
        {
            if (!await _materialClassTypeRepository.ExistsAsync(x => x.Id == input.TypeId && x.Type == input.TypeName))
            {
                throw new CustomException(Messages.MaterialClassTypeNotFound);
            }
            var materialClass = await _materialClassRepository.FindAsync(x => x.Id == input.Id);
            if (materialClass == null)
            {
                throw new CustomException(Messages.MaterialClassNotFound);
            }
            materialClass.TypeId = input.TypeId;
            materialClass.TypeName = input.TypeName;
            materialClass.Updatetime = DateTime.Now;
            int status = await _materialClassRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 删除物料类
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        /// <exception cref="CustomException"></exception>
        public async Task DeleteMaterialClassesAsync(IList<int> ids)
        {
            await _materialClassRepository.DeleteAsync(x => ids.Contains(x.Id));
            int status = await _materialClassRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 查询物料类
        /// </summary>
        /// <param name="input"></param>
        /// <returns>PagedItemsData<MaterialClassResult></returns>
        /// <exception cref="CustomException"></exception>
        public async Task<PagedItemsData<MaterialClassResult>> GetMaterialClassesAsync(GetMaterialClassesInput input)
        {
            Expression<Func<MaterialClass, bool>> filter = x => true;
            if (!string.IsNullOrEmpty(input.KeyWord))
            {
                filter = filter.And(x => x.Name.Contains(input.KeyWord) || x.Code.Contains(input.KeyWord));
            }
            var data = await _materialClassRepository.Query().Where(filter).OrderByDescending(x => x.CreateTime).ToPagedAsync(input.PagedInput);
            if (data == null)
            {
                throw new CustomException(Messages.MaterialClassNotFound);
            }
            return _mapper.Map<PagedItemsData<MaterialClassResult>>(data);
        }
    }
}
